use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};

use chrono::{Datelike, Timelike, Utc};
use common::{
    base::{config::Config, status::Status},
    serial::serial_db_colums,
};
use protobuf::CodedOutputStream;
use sqlparser::{
    ast::{
        Expr, ListAggOnOverflow, ObjectName, OnConflictAction, SelectItem, Statement, TableFactor,
        TableWithJoins,
    },
    dialect::MySqlDialect,
    parser::Parser,
};
use sqlx::{Column, Pool, Row, Transaction, TypeInfo};

use sqlx_mysql::{MySql, MySqlPoolOptions};
use tracing::{debug, info};


pub struct MySQLPool<'a> {
    pool: Pool<MySql>,

    connect_map: Mutex<HashMap<i64, Arc<tokio::sync::Mutex<MySQLConnect<'a>>>>>,
}

pub struct MySQLConnect<'a> {
    table_prefix: String,
    pool: Pool<MySql>,
    tx_num: u32,
    tx: Option<Transaction<'a, MySql>>,
}

impl<'a> MySQLPool<'a> {
    pub async fn new(config: &Box<Config>) -> MySQLPool<'a> {
        let ip = config.get_str("mysql", "ip").unwrap_or("127.0.0.1");
        let port = config.get_i32("mysql", "port").unwrap_or(3306);
        let username = config
            .get_str("mysql", "username")
            .expect("mysql 缺少 username");
        let password = config
            .get_str("mysql", "password")
            .expect("mysql 缺少 password");

        let database_url = format!("mysql://{}:{}@{}:{}/xport", username, password, ip, port);

        info!("连接 MySQL {}:{}", ip, port);

        let pool = MySqlPoolOptions::new().connect(&database_url).await;

        if pool.is_err() {
            panic!("连接数据库失败：{}", pool.err().unwrap());
        }

        info!("连接 MySQL {}:{} 成功", ip, port);

        MySQLPool {
            pool: pool.unwrap(),
            connect_map: Mutex::new(HashMap::new()),
        }
    }

    pub fn new_connection(
        &'a self,
        request_id: i64,
        table_prefix: String,
    ) -> Arc<tokio::sync::Mutex<MySQLConnect>> {
        let mut connect_map = self.connect_map.lock().unwrap();

        let connect = connect_map.get(&request_id);

        if connect.is_some() {
            return connect.unwrap().clone();
        }
        let connect = Arc::new(tokio::sync::Mutex::new(MySQLConnect {
            table_prefix,
            tx_num: 0,
            pool: self.pool.clone(),
            tx: None,
        }));
        connect_map.insert(request_id, connect.clone());
        connect
    }
    //
    pub fn putback_connection(&'a self, request_id: i64) {
        let mut connect_map = self.connect_map.lock().unwrap();

        connect_map.remove(&request_id);
    }

    pub fn get_connection(
        &'a self,
        request_id: i64,
    ) -> Option<Arc<tokio::sync::Mutex<MySQLConnect>>> {
        let connect_map = self.connect_map.lock().unwrap();
        let connect = connect_map.get(&request_id);

        if connect.is_none() {
            None
        } else {
            Some(connect.unwrap().clone())
        }
    }
}

impl<'a> MySQLConnect<'a> {
    //
    pub async fn is_table_exist(&mut self, table_name: &str) -> Result<bool, Status> {
        let rewrite_sql = format!("select table_name from information_schema.tables where table_schema = 'xport' and table_name = '{}_{}'", self.table_prefix, table_name);

        let result = if self.tx.is_some() {
            sqlx::query(rewrite_sql.as_str())
                .fetch_all(self.tx.as_mut().unwrap().as_mut())
                .await
        } else {
            sqlx::query(rewrite_sql.as_str())
                .fetch_all(&self.pool)
                .await
        };
        if result.is_err() {
            return Err(Status::error(result.err().unwrap().to_string()));
        }
        let result = result.unwrap();

        Ok(!result.is_empty())
    }
    //

    pub async fn query(&mut self, sql: &str) -> Result<Vec<u8>, Status> {
        debug!("sql = {}", sql);

        let rewrite_sql = self.rewrite_table_name(sql);

        let result = if self.tx.is_some() {
            sqlx::query(rewrite_sql.as_str())
                .fetch_all(self.tx.as_mut().unwrap().as_mut())
                .await
        } else {
            sqlx::query(rewrite_sql.as_str())
                .fetch_all(&self.pool)
                .await
        };
        if result.is_err() {
            return Err(Status::error(result.err().unwrap().to_string()));
        }
        //
        let result = result.unwrap();
        let mut column_map: HashMap<String, u32> = HashMap::new();
        let mut map_size = 0;
        let row_num = result.len();

        // 构建列名索引映射
        for sql_row in result.iter() {
            let columns = sql_row.columns();
            for column in columns {
                let mut entry_size = 0;
                let column_name = column.name();
                if !column_map.contains_key(column_name) {
                    let column_index = column.ordinal() as u32 + 1;
                    column_map
                        .entry(column.name().into())
                        .or_insert(column_index);
                    entry_size += ::protobuf::rt::string_size(1, column_name);
                    entry_size += ::protobuf::rt::uint32_size(2, column_index);
                    map_size +=
                        1 + ::protobuf::rt::compute_raw_varint64_size(entry_size) + entry_size
                    //
                }
            }
        }
        // 默认每一行的字节大小为 1024 个字节
        let mut buffer = Vec::with_capacity(map_size as usize + row_num * 1024);
        let mut os = CodedOutputStream::vec(&mut buffer);
        // 谢列头部
        serial_db_colums(map_size, &column_map, &mut os);
        // 遍历结果
        for sql_row in result.iter() {
            let columns = sql_row.columns();
            // 写入数据
            for column in columns {
                let column_name = column.name();
                let column_index = column_map.get(column_name).unwrap();
                let type_info = column.type_info();
                let type_name = type_info.name();
                match type_name {
                    "BOOLEAN" | "BIT" => {
                        let value: bool = sql_row.get(column_name);
                        os.write_bool(column_index.clone(), value).unwrap();
                    }
                    "TINYINT UNSIGNED" | "SMALLINT UNSIGNED" | "INT UNSIGNED"
                    | "MEDIUMINT UNSIGNED" | "YEAR" => {
                        let value: u32 = sql_row.get(column_name);
                        os.write_uint32(column_index.clone(), value).unwrap();
                    }
                    "TINYINT" | "SMALLINT" | "INT" | "MEDIUMINT" => {
                        let value: i32 = sql_row.get(column_name);
                        os.write_int32(column_index.clone(), value).unwrap();
                    }
                    "BIGINT UNSIGNED" => {
                        let value: u64 = sql_row.get(column_name);
                        os.write_uint64(column_index.clone(), value).unwrap();
                    }
                    "BIGINT" => {
                        let value: i64 = sql_row.get(column_name);
                        os.write_int64(column_index.clone(), value).unwrap();
                    }
                    "TIMESTAMP" => {
                        let value: chrono::DateTime<Utc> = sql_row.get(column.ordinal());
                        os.write_int64(column_index.clone(), value.timestamp_millis())
                            .unwrap();
                    }
                    "DATE" => {
                        let value: chrono::NaiveDate = sql_row.get(column.ordinal());
                        let ymd = value.year() as i64 * 10000
                            + value.month() as i64 * 100
                            + value.day() as i64;
                        os.write_int64(column_index.clone(), ymd).unwrap();
                    }
                    "TIME" => {
                        let value: chrono::NaiveTime = sql_row.get(column.ordinal());
                        let hms = value.hour() as i64 * 10000
                            + value.minute() as i64 * 100
                            + value.second() as i64;
                        os.write_int64(column_index.clone(), hms).unwrap();
                    }
                    "DATETIME" => {
                        let value: chrono::NaiveDateTime = sql_row.get(column.ordinal());
                        os.write_int64(column_index.clone(), value.timestamp_millis())
                            .unwrap();
                    }
                    "FLOAT" => {
                        let value: f32 = sql_row.get(column_name);
                        os.write_float(column_index.clone(), value).unwrap();
                    }
                    "DOUBLE" => {
                        let value: f64 = sql_row.get(column_name);
                        os.write_double(column_index.clone(), value).unwrap();
                    }
                    "TINYBLOB" | "BLOB" | "MEDIUMBLOB" | "LONGBLOB" | "VARBINARY" => {
                        let value: Vec<u8> = sql_row.get(column_name);
                        os.write_bytes(column_index.clone(), value.as_slice())
                            .unwrap();
                    }
                    "VARCHAR" | "CHAR" | "TINYTEXT" | "TEXT" | "MEDIUMTEXT" | "LONGTEXT"
                    | "ENUM" => {
                        let value: String = sql_row.get(column_name);
                        os.write_string(column_index.clone(), &value).unwrap();
                    }
                    _ => {}
                }
            }
            os.write_tag(1, protobuf::rt::WireType::EndGroup).unwrap();
        }
        drop(os);
        Ok(buffer)
    }

    /**
     * 返回 last_insert_id 和 affected_rows
     */
    pub async fn execute(&mut self, sql: &str) -> Result<(u64, u64), Status> {
        debug!("sql = {}", sql);

        let rewrite_sql = self.rewrite_table_name(sql);

        let result = if self.tx.is_some() {
            sqlx::query(rewrite_sql.as_str())
                .execute(self.tx.as_mut().unwrap().as_mut())
                .await
        } else {
            sqlx::query(rewrite_sql.as_str()).execute(&self.pool).await
        };

        if result.is_err() {
            return Err(Status::error(result.err().unwrap().to_string()));
        }

        let result = result.unwrap();

        let last_insert_id = result.last_insert_id();
        let affected_rows = result.rows_affected();

        Ok((last_insert_id, affected_rows))
    }

    pub async fn begin_tx(&mut self) {
        debug!("开启事务...");
        self.tx_num += 1;
        if self.tx.is_some() {
            return;
        }
        let tx: Result<Transaction<MySql>, sqlx_core::Error> = self.pool.begin().await;

        self.tx = Some(tx.unwrap());
    }

    pub async fn rollback(&mut self) -> Result<(), Status> {
        self.tx_num -= 1;
        if self.tx_num != 0 {
            return Ok(());
        }

        let tx = self.tx.take();

        if tx.is_none() {
            return Err(Status::error("事务不存在！".into()));
        }

        let result = tx.unwrap().rollback().await;
        debug!("回滚事务...");
        return if result.is_err() {
            Err(Status::error(result.err().unwrap().to_string()))
        } else {
            Ok(())
        };
    }

    pub async fn commit(&mut self) -> Result<(), Status> {
        self.tx_num -= 1;
        if self.tx_num != 0 {
            return Ok(());
        }

        let tx = self.tx.take();

        if tx.is_none() {
            return Err(Status::error("事务不存在！".into()));
        }

        let result = tx.unwrap().commit().await;
        debug!("提交事务...");
        return if result.is_err() {
            Err(Status::error(result.err().unwrap().to_string()))
        } else {
            Ok(())
        };
    }

    fn update_query_table_name_in_expr(&self, expr: &mut Expr) {
        match expr {
            sqlparser::ast::Expr::InSubquery {
                expr,
                subquery,
                negated,
            } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name(subquery);
            }
            sqlparser::ast::Expr::Subquery(subquery) => {
                self.update_query_table_name(subquery);
            }

            sqlparser::ast::Expr::JsonAccess {
                left,
                operator,
                right,
            } => {
                self.update_query_table_name_in_expr(left);
                self.update_query_table_name_in_expr(right);
            }
            sqlparser::ast::Expr::CompositeAccess { expr, key } => {
                self.update_query_table_name_in_expr(expr);
            }
            sqlparser::ast::Expr::IsFalse(expr)
            | sqlparser::ast::Expr::IsNotFalse(expr)
            | sqlparser::ast::Expr::IsTrue(expr)
            | sqlparser::ast::Expr::IsNotTrue(expr)
            | sqlparser::ast::Expr::IsNull(expr)
            | sqlparser::ast::Expr::IsNotNull(expr)
            | sqlparser::ast::Expr::IsUnknown(expr)
            | sqlparser::ast::Expr::IsNotUnknown(expr) => {
                self.update_query_table_name_in_expr(expr);
            }

            sqlparser::ast::Expr::IsDistinctFrom(left, right)
            | sqlparser::ast::Expr::IsNotDistinctFrom(left, right) => {
                self.update_query_table_name_in_expr(left);
                self.update_query_table_name_in_expr(right);
            }

            sqlparser::ast::Expr::InList {
                expr,
                list,
                negated,
            } => {
                self.update_query_table_name_in_expr(expr);
                for sub_expr in list {
                    self.update_query_table_name_in_expr(sub_expr);
                }
            }
            sqlparser::ast::Expr::InUnnest {
                expr,
                array_expr,
                negated,
            } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(array_expr);
            }
            sqlparser::ast::Expr::Between {
                expr,
                negated,
                low,
                high,
            } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(low);
                self.update_query_table_name_in_expr(high);
            }
            sqlparser::ast::Expr::BinaryOp { left, op, right } => {
                self.update_query_table_name_in_expr(left);
                self.update_query_table_name_in_expr(right);
            }

            sqlparser::ast::Expr::Like {
                negated,
                expr,
                pattern,
                escape_char,
            }
            | sqlparser::ast::Expr::ILike {
                negated,
                expr,
                pattern,
                escape_char,
            }
            | sqlparser::ast::Expr::SimilarTo {
                negated,
                expr,
                pattern,
                escape_char,
            } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(pattern);
            }

            sqlparser::ast::Expr::AnyOp(pattern) | sqlparser::ast::Expr::AllOp(pattern) => {
                self.update_query_table_name_in_expr(pattern);
            }

            sqlparser::ast::Expr::UnaryOp { op, expr } => {
                self.update_query_table_name_in_expr(expr);
            }
            sqlparser::ast::Expr::Cast { expr, .. }
            | sqlparser::ast::Expr::TryCast { expr, .. }
            | sqlparser::ast::Expr::SafeCast { expr, .. } => {
                self.update_query_table_name_in_expr(expr);
            }

            sqlparser::ast::Expr::AtTimeZone {
                timestamp,
                time_zone,
            } => {
                self.update_query_table_name_in_expr(timestamp);
            }
            sqlparser::ast::Expr::Extract { field, expr } => {
                self.update_query_table_name_in_expr(expr);
            }
            sqlparser::ast::Expr::Ceil { expr, .. } | sqlparser::ast::Expr::Floor { expr, .. } => {
                self.update_query_table_name_in_expr(expr);
            }

            sqlparser::ast::Expr::Position { expr, r#in } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(r#in);
            }
            sqlparser::ast::Expr::Substring {
                expr,
                substring_from,
                substring_for,
                special,
            } => {
                self.update_query_table_name_in_expr(expr);
                if substring_from.is_some() {
                    self.update_query_table_name_in_expr(substring_from.as_mut().unwrap());
                }
                if substring_for.is_some() {
                    self.update_query_table_name_in_expr(substring_for.as_mut().unwrap());
                }
            }
            sqlparser::ast::Expr::Trim {
                expr,
                trim_where,
                trim_what,
            } => {
                self.update_query_table_name_in_expr(expr);

                if trim_what.is_some() {
                    self.update_query_table_name_in_expr(trim_what.as_mut().unwrap());
                }
            }
            sqlparser::ast::Expr::Overlay {
                expr,
                overlay_what,
                overlay_from,
                overlay_for,
            } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(overlay_what);
                self.update_query_table_name_in_expr(overlay_from);

                if overlay_for.is_some() {
                    self.update_query_table_name_in_expr(overlay_for.as_mut().unwrap());
                }
            }
            sqlparser::ast::Expr::Collate { expr, collation } => {
                self.update_query_table_name_in_expr(expr);
            }
            sqlparser::ast::Expr::Nested(expr) => {
                self.update_query_table_name_in_expr(expr);
            }

            sqlparser::ast::Expr::MapAccess { column, keys } => {
                self.update_query_table_name_in_expr(column);

                for key in keys {
                    self.update_query_table_name_in_expr(key);
                }
            }

            sqlparser::ast::Expr::AggregateExpressionWithFilter { expr, filter } => {
                self.update_query_table_name_in_expr(expr);
                self.update_query_table_name_in_expr(filter);
            }
            sqlparser::ast::Expr::Case {
                operand,
                conditions,
                results,
                else_result,
            } => {
                if operand.is_some() {
                    self.update_query_table_name_in_expr(operand.as_mut().unwrap());
                }

                for condition in conditions {
                    self.update_query_table_name_in_expr(condition);
                }

                for result in results {
                    self.update_query_table_name_in_expr(result);
                }
                if else_result.is_some() {
                    self.update_query_table_name_in_expr(else_result.as_mut().unwrap());
                }
            }
            sqlparser::ast::Expr::Exists { subquery, negated } => {
                self.update_query_table_name(subquery);
            }
            sqlparser::ast::Expr::ArraySubquery(subquery) => {
                self.update_query_table_name(subquery);
            }
            sqlparser::ast::Expr::ListAgg(agg) => {
                self.update_query_table_name_in_expr(&mut agg.expr);
                if agg.separator.is_some() {
                    self.update_query_table_name_in_expr(agg.separator.as_mut().unwrap());
                }
                if agg.on_overflow.is_some() {
                    let on_overflow = agg.on_overflow.as_mut().unwrap();

                    match on_overflow {
                        ListAggOnOverflow::Truncate { filler, with_count } => {
                            if filler.is_some() {
                                self.update_query_table_name_in_expr(filler.as_mut().unwrap());
                            }
                        }
                        _ => {}
                    }
                }
                for within in &mut agg.within_group {
                    self.update_query_table_name_in_expr(&mut within.expr);
                }
            }
            sqlparser::ast::Expr::ArrayAgg(arr_agg) => {
                self.update_query_table_name_in_expr(&mut arr_agg.expr);
                if arr_agg.limit.is_some() {
                    self.update_query_table_name_in_expr(arr_agg.limit.as_mut().unwrap());
                }
                if arr_agg.order_by.is_some() {
                    let order_bys = arr_agg.order_by.as_mut().unwrap();

                    for order_by in order_bys {
                        self.update_query_table_name_in_expr(&mut order_by.expr);
                    }
                }
            }
            sqlparser::ast::Expr::GroupingSets(exprss)
            | sqlparser::ast::Expr::Cube(exprss)
            | sqlparser::ast::Expr::Rollup(exprss) => {
                for exprs in exprss {
                    for expr in exprs {
                        self.update_query_table_name_in_expr(expr);
                    }
                }
            }

            sqlparser::ast::Expr::Tuple(exprs) => {
                for expr in exprs {
                    self.update_query_table_name_in_expr(expr);
                }
            }
            sqlparser::ast::Expr::ArrayIndex { obj, indexes } => {
                self.update_query_table_name_in_expr(obj);

                for index in indexes {
                    self.update_query_table_name_in_expr(index);
                }
            }
            sqlparser::ast::Expr::Array(arr) => {
                for elem in &mut arr.elem {
                    self.update_query_table_name_in_expr(elem);
                }
            }
            sqlparser::ast::Expr::Interval(interval) => {
                self.update_query_table_name_in_expr(&mut interval.value);
            }
            _ => {}
        }
    }

    fn update_table_name(&self, table_name: &mut ObjectName) {
        let table_name = &mut table_name.0;

        for ident in table_name.iter_mut() {
            ident.value = format!("{}_{}", self.table_prefix, ident.value);
        }
    }
    //
    fn update_table_with_joins(&self, table_with_joins: &mut TableWithJoins) {
        match &mut table_with_joins.relation {
            TableFactor::Table {
                name,
                alias,
                args,
                with_hints,
                version,
            } => {
                self.update_table_name(name);
                for with_hint in with_hints {
                    self.update_query_table_name_in_expr(with_hint);
                }
            }
            TableFactor::Derived {
                lateral,
                subquery,
                alias,
            } => {
                self.update_query_table_name(subquery);
            }
            TableFactor::TableFunction { expr, alias } => {
                self.update_query_table_name_in_expr(expr);
            }
            TableFactor::UNNEST {
                alias,
                array_exprs,
                with_offset,
                with_offset_alias,
            } => {
                for array_expr in array_exprs {
                    self.update_query_table_name_in_expr(array_expr);
                }
            }
            TableFactor::NestedJoin {
                table_with_joins,
                alias,
            } => {
                self.update_table_with_joins(table_with_joins);
            }
            TableFactor::Pivot {
                name,
                table_alias,
                aggregate_function,
                value_column,
                pivot_values,
                pivot_alias,
            } => {
                self.update_table_name(name);
                self.update_query_table_name_in_expr(aggregate_function);
            }
        }
    }

    fn update_query_table_name(&self, query: &mut Box<sqlparser::ast::Query>) {
        match query.body.as_mut() {
            sqlparser::ast::SetExpr::Select(_select) => {
                for from in &mut _select.from {
                    self.update_table_with_joins(from);
                }

                for sub_selection in &mut _select.selection {
                    self.update_query_table_name_in_expr(sub_selection);
                }
            }
            sqlparser::ast::SetExpr::Query(_) => {
                let dsds = 9;
                let dsds = 9;
            }
            sqlparser::ast::SetExpr::SetOperation {
                op,
                set_quantifier,
                left,
                right,
            } => {
                let dsds = 9;
                let dsds = 9;
            }
            sqlparser::ast::SetExpr::Values(_) => {
                let dsds = 9;
                let dsds = 9;
            }
            sqlparser::ast::SetExpr::Insert(_) => {
                let dsds = 9;
                let dsds = 9;
            }
            sqlparser::ast::SetExpr::Update(_) => {
                let dsds = 9;
                let dsds = 9;
            }
            sqlparser::ast::SetExpr::Table(_) => {
                let dsds = 9;
                let dsds = 9;
            }
        }
    }

    fn update_select_items(&self, select_items: &mut Option<Vec<SelectItem>>) {
        if select_items.is_none() {
            return;
        }
        let select_items = select_items.as_mut().unwrap();

        for select_item in select_items {
            match select_item {
                SelectItem::UnnamedExpr(expr) => {
                    self.update_query_table_name_in_expr(expr);
                }
                SelectItem::ExprWithAlias { expr, alias } => {
                    self.update_query_table_name_in_expr(expr);
                }
                SelectItem::QualifiedWildcard(object_name, _) => {
                    self.update_table_name(object_name);
                }
                _ => {}
            }
        }
    }

    fn rewrite_table_name(&self, sql: &str) -> String {
        let dialect = MySqlDialect {};

        let mut ast = Parser::parse_sql(&dialect, sql).unwrap();

        let mut rewrite_sqls: Vec<String> = Vec::with_capacity(ast.len());

        for statement in &mut ast {
            match statement {
                Statement::CreateTable {
                    or_replace,
                    temporary,
                    external,
                    global,
                    if_not_exists,
                    transient,
                    name,
                    columns,
                    constraints,
                    hive_distribution,
                    hive_formats,
                    table_properties,
                    with_options,
                    file_format,
                    location,
                    query,
                    without_rowid,
                    like,
                    clone,
                    engine,
                    default_charset,
                    collation,
                    on_commit,
                    on_cluster,
                    order_by,
                    strict,
                    comment,
                    auto_increment_offset,
                } => {
                    self.update_table_name(name);
                }
                Statement::Query(query) => {
                    self.update_query_table_name(query);
                }
                Statement::Insert {
                    or,
                    into,
                    table_name,
                    columns,
                    overwrite,
                    source,
                    partitioned,
                    after_columns,
                    table,
                    on,
                    returning,
                } => {
                    self.update_table_name(table_name);

                    self.update_query_table_name(source);
                    if partitioned.is_some() {
                        let partitioneds = partitioned.as_mut().unwrap();
                        for partitioned in partitioneds {
                            self.update_query_table_name_in_expr(partitioned);
                        }
                    }

                    if on.is_some() {
                        let on = on.as_mut().unwrap();

                        match on {
                            sqlparser::ast::OnInsert::DuplicateKeyUpdate(assignments) => {
                                for assignment in assignments {
                                    self.update_query_table_name_in_expr(&mut assignment.value);
                                }
                            }
                            sqlparser::ast::OnInsert::OnConflict(conflict) => {
                                if conflict.conflict_target.is_some() {
                                    if let sqlparser::ast::ConflictTarget::OnConstraint(
                                        constraint,
                                    ) = conflict.conflict_target.as_mut().unwrap()
                                    {
                                        self.update_table_name(constraint);
                                    }
                                }
                                if let OnConflictAction::DoUpdate(do_update) = &mut conflict.action
                                {
                                    for assignment in do_update.assignments.iter_mut() {
                                        self.update_query_table_name_in_expr(&mut assignment.value);
                                    }
                                    if do_update.selection.is_some() {
                                        self.update_query_table_name_in_expr(
                                            do_update.selection.as_mut().unwrap(),
                                        );
                                    }
                                }
                            }
                            _ => {}
                        }
                    }

                    self.update_select_items(returning);
                }
                Statement::Update {
                    table,
                    assignments,
                    from,
                    selection,
                    returning,
                } => {
                    self.update_table_with_joins(table);

                    for assignment in assignments {
                        self.update_query_table_name_in_expr(&mut assignment.value);
                    }

                    if from.is_some() {
                        self.update_table_with_joins(from.as_mut().unwrap());
                    }

                    if selection.is_some() {
                        self.update_query_table_name_in_expr(selection.as_mut().unwrap());
                    }
                    self.update_select_items(returning);
                }
                Statement::Delete {
                    tables,
                    from,
                    using,
                    selection,
                    returning,
                } => {
                    for table in tables.iter_mut() {
                        self.update_table_name(table);
                    }

                    for from in from {
                        self.update_table_with_joins(from);
                    }

                    if using.is_some() {
                        let usings = using.as_mut().unwrap();
                        for using in usings {
                            self.update_table_with_joins(using);
                        }
                    }

                    if selection.is_some() {
                        self.update_query_table_name_in_expr(selection.as_mut().unwrap());
                    }
                    self.update_select_items(returning);
                }

                _ => {}
            };
            rewrite_sqls.push(statement.to_string());
        }
        rewrite_sqls.join(";")
    }
}
